/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "Attest_spt_fp.h"
#include "CertifyCreation_fp.h"

#if CC_CertifyCreation  // Conditional expansion of this file

/*(See part 3 specification)
// Prove the association between an object and its creation data
*/
//  Return Type: TPM_RC
//      TPM_RC_KEY          key referenced by 'signHandle' is not a signing key
//      TPM_RC_SCHEME       'inScheme' is not compatible with 'signHandle'
//      TPM_RC_TICKET       'creationTicket' does not match 'objectHandle'
//      TPM_RC_VALUE        digest generated for 'inScheme' is greater or has larger
//                          size than the modulus of 'signHandle', or the buffer for
//                          the result in 'signature' is too small (for an RSA key);
//                          invalid commit status (for an ECC key with a split scheme).
/*
Part3
This command is used to prove the association between an object and its creation data. 
The TPM will validate that the ticket was produced by the TPM and that the ticket validates 
the association between a loaded public area and the provided hash of the creation data (creationHash).
此命令用于证明对象与其创建数据之间的关联。
TPM 将验证票证是否由 TPM 生成，并且票证验证加载的公共区域与提供的创建数据哈希 (creationHash) 之间的关联。

The TPM will create a test ticket using the Name associated with objectHandle and creationHash as:
HMAC(proof, (TPM_ST_CREATION || objectHandle→Name || creationHash)) (4)
This ticket is then compared to creation ticket. If the tickets are not the same, the TPM shall return TPM_RC_TICKET.
If the ticket is valid, then the TPM will create a TPMS_ATTEST structure and place creationHash of the command in the 
creationHash field of the structure. The Name associated with objectHandle will be included in the attestation data that 
is then signed using the key associated with signHandle.

TPM 将使用与 objectHandle 和 creationHash 关联的 Name 创建一个测试票据，如下所示：
HMAC(proof, (TPM_ST_CREATION || objectHandle→Name || creationHash)) (4)
然后将这张票与创建票进行比较。 如果门票不同，TPM 将返回 TPM_RC_TICKET。
如果票证有效，则 TPM 将创建一个 TPMS_ATTEST 结构并将命令的 creationHash 放入该结构的 creationHash 字段中。 与 objectHandle 
关联的名称将包含在证明数据中，然后使用与 signHandle 关联的密钥对其进行签名。

NOTE 2 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL Signature.
objectHandle may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary()
注 2 如果 signHandle 是 TPM_RH_NULL，则返回 TPMS_ATTEST 结构并且签名是 NULL 签名。
objectHandle 可以是使用 TPM2_Load() 或 TPM2_CreatePrimary() 加载的任何对象

*/
TPM_RC
TPM2_CertifyCreation(
    CertifyCreation_In      *in,            // IN: input parameter list
    CertifyCreation_Out     *out            // OUT: output parameter list
    )
{
    TPMT_TK_CREATION        ticket;
    TPMS_ATTEST             certifyInfo;
    OBJECT                  *certified = HandleToObject(in->objectHandle);
    OBJECT                  *signObject = HandleToObject(in->signHandle);
// Input Validation
    if(!IsSigningObject(signObject))
        return TPM_RCS_KEY + RC_CertifyCreation_signHandle;
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
        return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme;

    // CertifyCreation specific input validation
    // Re-compute ticket
    TicketComputeCreation(in->creationTicket.hierarchy, &certified->name,
                          &in->creationHash, &ticket);
    // Compare ticket
    if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b))
        return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket;

// Command Output
    // Common fields
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
                     &certifyInfo);

    // CertifyCreation specific fields
    // Attestation type
    certifyInfo.type = TPM_ST_ATTEST_CREATION;
    certifyInfo.attested.creation.objectName = certified->name;

    // Copy the creationHash
    certifyInfo.attested.creation.creationHash = in->creationHash;

    // Sign attestation structure.  A NULL signature will be returned if
    // signObject is TPM_RH_NULL.  A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
    // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
    // this point
    return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
                          &in->qualifyingData, &out->certifyInfo,
                          &out->signature);
}

#endif // CC_CertifyCreation